package com.luo.sc.oidc.authserver.handler.login;

import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;


/**
 * 通用登录 - 认证过滤器
 *
 * @author luohq
 * @version 1.0.0
 * @date 2022-03-03、
 * @see org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
 */
public class UniLoginAuthenticationProcessingFilter extends AbstractAuthenticationProcessingFilter {

    private boolean postOnly = true;

    public UniLoginAuthenticationProcessingFilter(String loginProcessingUrl, AuthenticationManager authenticationManager) {
        super(new AntPathRequestMatcher(loginProcessingUrl, "POST"), authenticationManager);
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
        //仅支持POST请求
        if (this.postOnly && !request.getMethod().equals("POST")) {
            throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
        }
        //初始认证信息
        UniLoginAuthenticationToken authRequest = new UniLoginAuthenticationToken(this.getAuthParams(request));
        // Allow subclasses to set the "details" property
        setDetails(request, authRequest);
        //调用认证管理器进行验证（即调用UniLoginAuthenticationProvider）
        return this.getAuthenticationManager().authenticate(authRequest);
    }

    /**
     * 获取登录表单参数Map
     *
     * @param request 登录请求
     * @return 登录表单参数Map
     */
    private Map<String, String> getAuthParams(HttpServletRequest request) {
        //提取全部form参数
        Map<String, String[]> originRequestParamMap = request.getParameterMap();
        Assert.notEmpty(originRequestParamMap, "Uni Login Auth Params should not empty!");
        //转换后的form参数
        Map<String, String> convertRequestParamMap = new HashMap<>(originRequestParamMap.size());
        //转换form参数
        for (Map.Entry<String, String[]> entry : originRequestParamMap.entrySet()) {
            String paramName = entry.getKey();
            String[] paramVals = entry.getValue();
            if (null == paramVals || 0 >= paramVals.length || !StringUtils.hasText(paramVals[0])) {
                continue;
            }
            convertRequestParamMap.put(paramName, paramVals[0]);
        }
        return convertRequestParamMap;
    }


    protected void setDetails(HttpServletRequest request, UniLoginAuthenticationToken authRequest) {
        authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));
    }

}